package com.dcy.machine.config.order;

import com.dcy.machine.enums.OrderEvent;
import com.dcy.machine.enums.OrderStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.region.RegionExecutionPolicy;
import org.springframework.statemachine.transition.TransitionConflictPolicy;

import java.util.EnumSet;

/**
 * @Author：dcy
 * @Description:
 * @Date: 2021/11/9 14:03
 */
@Slf4j
@Configuration
@EnableStateMachineFactory(name = OrderStateMachineConfig.ORDER_STATE_MACHINE_FACTORY_NAME)
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderEvent> {

    /**
     * 订单状态机ID
     */
    public static final String ORDER_STATE_MACHINE_ID = "orderStateMachineId";
    /**
     * 订单状态机工厂名称
     */
    public static final String ORDER_STATE_MACHINE_FACTORY_NAME = "orderStateMachineFactory";

    /**
     * 状态监听器
     *
     * @param config
     * @throws Exception
     */
    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStatus, OrderEvent> config) throws Exception {
        config
                .withConfiguration()
                .machineId(ORDER_STATE_MACHINE_ID)
                .transitionConflictPolicy(TransitionConflictPolicy.CHILD)
                .regionExecutionPolicy(RegionExecutionPolicy.PARALLEL);
    }

    /**
     * 配置状态
     *
     * @param states
     * @throws Exception
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states) throws Exception {
        states
                .withStates()
                //定义了初始状态
                .initial(OrderStatus.WAIT_PAYMENT)
                // 定义结束状态
                .end(OrderStatus.FINISH)
                //指定了使用上一步中定义的所有状态作为该状态机的状态定义
                .states(EnumSet.allOf(OrderStatus.class));
    }

    /**
     * 配置状态转换事件关系
     * 命名中我们很容易理解每一个迁移动作，都有来源状态source，目标状态target以及触发事件event
     *
     * @param transitions
     * @throws Exception
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions) throws Exception {
        transitions
                // 待支付 到 待发货 的事件 支付
                .withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderEvent.PAYED)
                .and()
                // 待发货 到 待收货 的事件 发货
                .withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderEvent.DELIVERY)
                .and()
                // 待收货 到 订单结束 的事件 确认收货
                .withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderEvent.RECEIVED);
    }
}
